package com.example.dianproject.service.impl;

import com.example.dianproject.entity.Meter;
import com.example.dianproject.entity.MeterReading;
import com.example.dianproject.repository.MeterReadingRepository;
import com.example.dianproject.repository.MeterRepository;
import com.example.dianproject.service.MeterReadingService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.time.LocalDate;
import java.util.List;
import java.util.Optional;

@Service
public class MeterReadingServiceImpl implements MeterReadingService {

    @Autowired
    private MeterReadingRepository meterReadingRepository;

    @Autowired
    private MeterRepository meterRepository;

    @Override
    @Transactional
    public MeterReading save(MeterReading meterReading) {
        // 如果是更新操作，先获取原记录
        MeterReading existingReading = null;
        if (meterReading.getReadingId() != null) {
            existingReading = meterReadingRepository.findById(meterReading.getReadingId()).orElse(null);
        }

        // 保存抄表记录
        MeterReading savedReading = meterReadingRepository.save(meterReading);
        
        // 更新电表的当前读数
        Optional<Meter> meterOpt = meterRepository.findById(meterReading.getMeterId());
        if (meterOpt.isPresent()) {
            Meter meter = meterOpt.get();
            meter.setCurrentReading(meterReading.getCurrentReading());
            meterRepository.save(meter);
            
            // 设置关联的电表信息
            savedReading.setMeter(meter);
            
            // 如果是更新操作，需要更新后续记录的上次读数
            if (existingReading != null) {
                updateSubsequentReadings(existingReading.getMeterId(), 
                                      existingReading.getReadingDate(), 
                                      meterReading.getCurrentReading());
            }
        }
        
        return savedReading;
    }

    /**
     * 更新指定日期之后的所有抄表记录的上次读数
     */
    private void updateSubsequentReadings(Long meterId, LocalDate afterDate, BigDecimal newPreviousReading) {
        List<MeterReading> subsequentReadings = meterReadingRepository
            .findByMeterIdAndReadingDateAfterOrderByReadingDateAsc(meterId, afterDate);
        
        BigDecimal lastReading = newPreviousReading;
        for (MeterReading reading : subsequentReadings) {
            reading.setPreviousReading(lastReading);
            // 重新计算用电量
            reading.setElectricityUsage(reading.getCurrentReading().subtract(lastReading));
            meterReadingRepository.save(reading);
            lastReading = reading.getCurrentReading();
        }
    }

    @Override
    @Transactional(readOnly = true)
    public MeterReading findById(Long id) {
        return meterReadingRepository.findById(id)
            .map(reading -> {
                // 确保加载关联的电表信息
                if (reading.getMeterId() != null) {
                    meterRepository.findById(reading.getMeterId())
                        .ifPresent(reading::setMeter);
                }
                return reading;
            })
            .orElse(null);
    }

    @Override
    @Transactional(readOnly = true)
    public List<MeterReading> findAll() {
        List<MeterReading> readings = meterReadingRepository.findAll();
        // 确保加载所有关联的电表信息
        readings.forEach(reading -> {
            if (reading.getMeterId() != null) {
                meterRepository.findById(reading.getMeterId())
                    .ifPresent(reading::setMeter);
            }
        });
        return readings;
    }

    @Override
    @Transactional
    public void deleteById(Long id) {
        meterReadingRepository.deleteById(id);
    }

    @Override
    @Transactional(readOnly = true)
    public List<MeterReading> findByMeterId(Long meterId) {
        List<MeterReading> readings = meterReadingRepository.findByMeterIdOrderByReadingDateDesc(meterId);
        // 确保加载关联的电表信息
        if (!readings.isEmpty()) {
            Optional<Meter> meter = meterRepository.findById(meterId);
            meter.ifPresent(m -> readings.forEach(r -> r.setMeter(m)));
        }
        return readings;
    }

    @Override
    @Transactional(readOnly = true)
    public List<MeterReading> findByDateRange(LocalDate startDate, LocalDate endDate) {
        List<MeterReading> readings = meterReadingRepository.findByReadingDateBetweenOrderByReadingDateDesc(startDate, endDate);
        // 确保加载所有关联的电表信息
        readings.forEach(reading -> {
            if (reading.getMeterId() != null) {
                meterRepository.findById(reading.getMeterId())
                    .ifPresent(reading::setMeter);
            }
        });
        return readings;
    }

    @Override
    @Transactional(readOnly = true)
    public MeterReading getLatestReading(Long meterId) {
        MeterReading reading = meterReadingRepository.findFirstByMeterIdOrderByReadingDateDesc(meterId);
        if (reading != null && reading.getMeterId() != null) {
            meterRepository.findById(reading.getMeterId())
                .ifPresent(reading::setMeter);
        }
        return reading;
    }

    @Override
    @Transactional(readOnly = true)
    public Long getPendingReadingsCount() {
        // 获取所有电表数量
        long totalMeters = meterRepository.count();
        
        // 获取本月已抄表数量
        long readMeters = meterReadingRepository.countByReadingDateBetween(
            LocalDate.now().withDayOfMonth(1),
            LocalDate.now()
        );
        
        // 待抄表数 = 总电表数 - 本月已抄表数
        return totalMeters - readMeters;
    }

    @Override
    @Transactional(readOnly = true)
    public Long getCurrentMonthReadingsCount() {
        return meterReadingRepository.countByReadingDateBetween(
            LocalDate.now().withDayOfMonth(1),
            LocalDate.now()
        );
    }

    @Override
    @Transactional(readOnly = true)
    public List<MeterReading> getRecentReadings(int limit) {
        PageRequest pageRequest = PageRequest.of(0, limit, 
            Sort.by(Sort.Direction.DESC, "readingDate", "createdTime"));
        return meterReadingRepository.findRecentReadings(pageRequest);
    }
} 